home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / gui / gtlayout.lha / Source / LTP_LevelClass.c < prev    next >
C/C++ Source or Header  |  1999-01-02  |  29KB  |  1,329 lines

  1. /*
  2. **    GadTools layout toolkit
  3. **
  4. **    Copyright © 1993-1999 by Olaf `Olsen' Barthel
  5. **        Freely distributable.
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #ifndef _GTLAYOUT_GLOBAL_H
  11. #include "gtlayout_global.h"
  12. #endif
  13.  
  14. /*****************************************************************************/
  15.  
  16. #include <graphics/gfxmacros.h>
  17.  
  18. #include <clib/alib_protos.h>    /* For Coerce/Do/DoSuperMethod */
  19.  
  20. #include <stdarg.h>
  21.  
  22. /*****************************************************************************/
  23.  
  24. #include "Assert.h"
  25.  
  26. #ifdef DO_LEVEL_KIND    /* Support code */
  27.  
  28.  
  29. /*****************************************************************************/
  30.  
  31. #define FAILED (0)
  32.  
  33. /*****************************************************************************/
  34.  
  35.  
  36. STATIC VOID
  37. SliderCleanup(struct SliderClassData *sd)
  38. {
  39.     LONG i;
  40.  
  41.     WaitBlit();
  42.  
  43.     for(i = 0 ; i < sd->ThumbBitMap.Depth ; i++)
  44.     {
  45.         if(sd->ThumbBitMap.Planes[i] != NULL)
  46.         {
  47.             FreeRaster(sd->ThumbBitMap.Planes[i],sd->ThumbWidth * 2,sd->ThumbHeight);
  48.             sd->ThumbBitMap.Planes[i] = NULL;
  49.         }
  50.     }
  51. }
  52.  
  53. /****************************************************************************/
  54.  
  55. #define SCALE_UP(a)        ((a) * dri->dri_Resolution.Y)/dri->dri_Resolution.X
  56. #define SCALE_DOWN(a)    ((a) * dri->dri_Resolution.X)/dri->dri_Resolution.Y
  57.  
  58. /****************************************************************************/
  59.  
  60. LONG
  61. LTP_QuerySliderSize(struct DrawInfo *dri,WORD Reference,WORD freedom,WORD useTicks)
  62. {
  63.     LONG thumbWidth,thumbHeight,separatorSpace,pipSpace,result;
  64.  
  65.     if(Reference == 0)
  66.         Reference = dri->dri_Font->tf_YSize;
  67.  
  68.     thumbHeight = (Reference + 1) & ~1;
  69.  
  70.     if(thumbHeight < 8)
  71.         thumbHeight = 8;
  72.  
  73.     thumbWidth = (((thumbHeight * 1618) / 1000) + 1) & ~1;
  74.  
  75.     if(thumbWidth < 8)
  76.         thumbWidth = 8;
  77.  
  78.     thumbHeight = SCALE_DOWN(thumbHeight);
  79.  
  80.     if(thumbHeight < 8)
  81.         thumbHeight = 8;
  82.  
  83.     if(freedom == FREEVERT)
  84.     {
  85.         separatorSpace    = 2;
  86.         pipSpace        = SCALE_UP(4);
  87.  
  88.         if(useTicks != TICKS_None)
  89.         {
  90.             result = separatorSpace + pipSpace + separatorSpace + thumbWidth + separatorSpace;
  91.  
  92.             if(useTicks == TICKS_Both)
  93.                 result += pipSpace + separatorSpace;
  94.         }
  95.         else
  96.         {
  97.             result = separatorSpace + thumbWidth + separatorSpace;
  98.         }
  99.     }
  100.     else
  101.     {
  102.         separatorSpace    = 2;
  103.         pipSpace        = SCALE_DOWN(4);
  104.  
  105.         if(useTicks != TICKS_None)
  106.         {
  107.             result = separatorSpace + pipSpace + separatorSpace + thumbHeight + separatorSpace;
  108.  
  109.             if(useTicks == TICKS_Both)
  110.                 result += pipSpace + separatorSpace;
  111.         }
  112.         else
  113.         {
  114.             result = separatorSpace + thumbHeight + separatorSpace;
  115.         }
  116.     }
  117.  
  118.     return(result);
  119. }
  120.  
  121. STATIC BOOL
  122. SliderSetup(struct SliderClassData *sd,WORD Reference,LONG Dimension)
  123. {
  124.     struct DrawInfo *dri = sd->DrawInfo;
  125.     BOOL IsVertical = sd->IsVertical;
  126.     BOOL GotPlanes;
  127.     LONG i;
  128.  
  129.     if(Reference == 0)
  130.         Reference = dri->dri_Font->tf_YSize;
  131.  
  132.     sd->ThumbHeight = (Reference + 1) & ~1;
  133.  
  134.     if(sd->ThumbHeight < 8)
  135.         sd->ThumbHeight = 8;
  136.  
  137.     sd->ThumbWidth = (((sd->ThumbHeight * 1618) / 1000) + 1) & ~1;
  138.  
  139.     if(sd->ThumbWidth < 8)
  140.         sd->ThumbWidth = 8;
  141.  
  142.     sd->ThumbHeight = SCALE_DOWN(sd->ThumbHeight);
  143.  
  144.     if(sd->ThumbHeight < 8)
  145.         sd->ThumbHeight = 8;
  146.  
  147.     InitBitMap(&sd->ThumbBitMap,min(8,dri->dri_Depth),sd->ThumbWidth * 2,sd->ThumbHeight);
  148.  
  149.     GotPlanes = TRUE;
  150.  
  151.     for(i = 0 ; i < sd->ThumbBitMap.Depth ; i++)
  152.     {
  153.         sd->ThumbBitMap.Planes[i] = AllocRaster(sd->ThumbWidth * 2,sd->ThumbHeight);
  154.         if(sd->ThumbBitMap.Planes[i] == NULL)
  155.         {
  156.             GotPlanes = FALSE;
  157.             break;
  158.         }
  159.     }
  160.  
  161.     if(GotPlanes)
  162.     {
  163.         struct RastPort rp;
  164.         UWORD *pens = dri->dri_Pens;
  165.         LONG width,height;
  166.  
  167.         width = height = Dimension;
  168.  
  169.         InitRastPort(&rp);
  170.         rp.BitMap = &sd->ThumbBitMap;
  171.  
  172.         SetRast(&rp,pens[BACKGROUNDPEN]);
  173.  
  174.         SetDrMd(&rp,JAM1);
  175.  
  176.         SetAPen(&rp,pens[SHINEPEN]);
  177.  
  178.         if(IsVertical)
  179.         {
  180.             Move(&rp,0,(sd->ThumbHeight / 2) - 2);
  181.             Draw(&rp,0,0);
  182.             Draw(&rp,sd->ThumbWidth - 2,0);
  183.  
  184.             Move(&rp,0,sd->ThumbHeight - 2);
  185.             Draw(&rp,0,sd->ThumbHeight / 2);
  186.             Draw(&rp,sd->ThumbWidth - 2,sd->ThumbHeight / 2);
  187.  
  188.             SetAPen(&rp,pens[SHADOWPEN]);
  189.  
  190.             Move(&rp,1,(sd->ThumbHeight / 2) - 1);
  191.             Draw(&rp,sd->ThumbWidth - 1,(sd->ThumbHeight / 2) - 1);
  192.             Draw(&rp,sd->ThumbWidth - 1,1);
  193.  
  194.             Move(&rp,1,sd->ThumbHeight - 1);
  195.             Draw(&rp,sd->ThumbWidth - 1,sd->ThumbHeight - 1);
  196.             Draw(&rp,sd->ThumbWidth - 1,(sd->ThumbHeight / 2) + 1);
  197.  
  198.             sd->SeparatorSpace    = 2;
  199.             sd->TickSpace        = SCALE_UP(4);
  200.  
  201.             if(sd->UseTicks != TICKS_None)
  202.             {
  203.                 sd->Width        = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + sd->ThumbWidth + sd->SeparatorSpace;
  204.                 sd->Height        = height;
  205.  
  206.                 sd->TickTop        = sd->SeparatorSpace;
  207.                 sd->RailTop        = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + (sd->ThumbWidth / 2) - 2;
  208.                 sd->ThumbTop    = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace;
  209.  
  210.                 if(sd->UseTicks == TICKS_Both)
  211.                     sd->Width += sd->TickSpace + sd->SeparatorSpace;
  212.             }
  213.             else
  214.             {
  215.                 sd->Width        = sd->SeparatorSpace + sd->ThumbWidth + sd->SeparatorSpace;
  216.                 sd->Height        = height;
  217.  
  218.                 sd->TickTop        = sd->SeparatorSpace;
  219.                 sd->RailTop        = sd->SeparatorSpace + (sd->ThumbWidth / 2) - 2;
  220.                 sd->ThumbTop    = sd->SeparatorSpace;
  221.             }
  222.  
  223.             sd->ThumbLast = sd->Height - sd->ThumbHeight;
  224.  
  225.             if(sd->ThumbMax == 0)
  226.                 sd->ThumbLeft = 0;
  227.             else
  228.                 sd->ThumbLeft = (sd->ThumbLast * sd->ThumbPosition) / sd->ThumbMax;
  229.  
  230.             ClipBlit(&rp,0,0,&rp,sd->ThumbWidth,0,sd->ThumbWidth,sd->ThumbHeight,0xC0);
  231.             SetAPen(&rp,pens[FILLPEN]);
  232.  
  233.             RectFill(&rp,sd->ThumbWidth + 1,1,sd->ThumbWidth + sd->ThumbWidth - 2,(sd->ThumbHeight / 2) - 2);
  234.             RectFill(&rp,sd->ThumbWidth + 1,(sd->ThumbHeight / 2) + 1,sd->ThumbWidth + sd->ThumbWidth - 2,sd->ThumbHeight - 2);
  235.         }
  236.         else
  237.         {
  238.             Move(&rp,(sd->ThumbWidth / 2) - 2,0);
  239.             Draw(&rp,0,0);
  240.             Draw(&rp,0,sd->ThumbHeight - 2);
  241.  
  242.             Move(&rp,sd->ThumbWidth - 2,0);
  243.             Draw(&rp,sd->ThumbWidth / 2,0);
  244.             Draw(&rp,sd->ThumbWidth / 2,sd->ThumbHeight - 2);
  245.  
  246.             SetAPen(&rp,pens[SHADOWPEN]);
  247.  
  248.             Move(&rp,(sd->ThumbWidth / 2) - 1,1);
  249.             Draw(&rp,(sd->ThumbWidth / 2) - 1,sd->ThumbHeight - 1);
  250.             Draw(&rp,1,sd->ThumbHeight - 1);
  251.  
  252.             Move(&rp,sd->ThumbWidth - 1,1);
  253.             Draw(&rp,sd->ThumbWidth - 1,sd->ThumbHeight - 1);
  254.             Draw(&rp,(sd->ThumbWidth / 2) + 1,sd->ThumbHeight - 1);
  255.  
  256.             sd->SeparatorSpace    = 2;
  257.             sd->TickSpace        = SCALE_DOWN(4);
  258.  
  259.             if(sd->UseTicks != TICKS_None)
  260.             {
  261.                 sd->Width        = width;
  262.                 sd->Height        = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + sd->ThumbHeight + sd->SeparatorSpace;
  263.  
  264.                 sd->TickTop        = sd->SeparatorSpace;
  265.                 sd->RailTop        = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace + (sd->ThumbHeight / 2) - 2;
  266.                 sd->ThumbTop    = sd->SeparatorSpace + sd->TickSpace + sd->SeparatorSpace;
  267.  
  268.                 if(sd->UseTicks == TICKS_Both)
  269.                     sd->Height += sd->TickSpace + sd->SeparatorSpace;
  270.             }
  271.             else
  272.             {
  273.                 sd->Width        = width;
  274.                 sd->Height        = sd->SeparatorSpace + sd->ThumbHeight + sd->SeparatorSpace;
  275.  
  276.                 sd->TickTop        = sd->SeparatorSpace;
  277.                 sd->RailTop        = sd->SeparatorSpace + (sd->ThumbHeight / 2) - 2;
  278.                 sd->ThumbTop    = sd->SeparatorSpace;
  279.             }
  280.  
  281.             sd->ThumbLast = sd->Width - sd->ThumbWidth;
  282.  
  283.             if(sd->ThumbMax == 0)
  284.                 sd->ThumbLeft = 0;
  285.             else
  286.                 sd->ThumbLeft = (sd->ThumbLast * sd->ThumbPosition) / sd->ThumbMax;
  287.  
  288.             ClipBlit(&rp,0,0,&rp,sd->ThumbWidth,0,sd->ThumbWidth,sd->ThumbHeight,0xC0);
  289.             SetAPen(&rp,pens[FILLPEN]);
  290.  
  291.             RectFill(&rp,sd->ThumbWidth + 1,1,sd->ThumbWidth + (sd->ThumbWidth / 2) - 2,sd->ThumbHeight - 2);
  292.             RectFill(&rp,sd->ThumbWidth + (sd->ThumbWidth / 2) + 1,1,sd->ThumbWidth + sd->ThumbWidth - 2,sd->ThumbHeight - 2);
  293.         }
  294.     }
  295.     else
  296.     {
  297.         SliderCleanup(sd);
  298.     }
  299.  
  300.     return(GotPlanes);
  301. }
  302.  
  303. STATIC VOID
  304. DrawTicks(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
  305. {
  306.     if(sd->UseTicks != TICKS_None)
  307.     {
  308.         LONG numTicks,maxTicks;
  309.  
  310.         if(sd->IsVertical)
  311.             maxTicks = (sd->Height - sd->ThumbHeight + 4) / 4;
  312.         else
  313.             maxTicks = (sd->Width - sd->ThumbWidth + 4) / 4;
  314.  
  315.         if(sd->NumTicks > 0)
  316.             numTicks = sd->NumTicks;
  317.         else
  318.             numTicks = sd->ThumbMax + 1;
  319.  
  320.         while(numTicks > maxTicks && numTicks > 1)
  321.             numTicks = numTicks / 2;
  322.  
  323.         if(numTicks > 1)
  324.         {
  325.             LONG x,y,i;
  326.  
  327.             if(sd->IsVertical)
  328.             {
  329.                 for(i = 0 ; i < numTicks ; i++)
  330.                 {
  331.                     x = left + sd->TickTop;
  332.                     y = top + (i * (sd->Height - sd->ThumbHeight)) / (numTicks - 1) + (sd->ThumbHeight / 2) - 1;
  333.  
  334.                     SetAPen(rp,pens[SHADOWPEN]);
  335.                     Move(rp,x,y);
  336.                     Draw(rp,x + sd->TickSpace - 1,y);
  337.  
  338.                     SetAPen(rp,pens[SHINEPEN]);
  339.                     Move(rp,x,y + 1);
  340.                     Draw(rp,x + sd->TickSpace - 1,y + 1);
  341.  
  342.                     if(sd->UseTicks == TICKS_Both)
  343.                     {
  344.                         x += sd->TickSpace + sd->SeparatorSpace + sd->ThumbWidth + sd->SeparatorSpace;
  345.  
  346.                         SetAPen(rp,pens[SHADOWPEN]);
  347.                         Move(rp,x,y);
  348.                         Draw(rp,x + sd->TickSpace - 1,y);
  349.  
  350.                         SetAPen(rp,pens[SHINEPEN]);
  351.                         Move(rp,x,y + 1);
  352.                         Draw(rp,x + sd->TickSpace - 1,y + 1);
  353.                     }
  354.                 }
  355.             }
  356.             else
  357.             {
  358.                 for(i = 0 ; i < numTicks ; i++)
  359.                 {
  360.                     x = left + (i * (sd->Width - sd->ThumbWidth)) / (numTicks - 1) + (sd->ThumbWidth / 2) - 1;
  361.                     y = top + sd->TickTop;
  362.  
  363.                     SetAPen(rp,pens[SHADOWPEN]);
  364.                     Move(rp,x,y);
  365.                     Draw(rp,x,y + sd->TickSpace - 1);
  366.  
  367.                     SetAPen(rp,pens[SHINEPEN]);
  368.                     Move(rp,x + 1,y);
  369.                     Draw(rp,x + 1,y + sd->TickSpace - 1);
  370.  
  371.                     if(sd->UseTicks == TICKS_Both)
  372.                     {
  373.                         y += sd->TickSpace + sd->SeparatorSpace + sd->ThumbHeight + sd->SeparatorSpace;
  374.  
  375.                         SetAPen(rp,pens[SHADOWPEN]);
  376.                         Move(rp,x,y);
  377.                         Draw(rp,x,y + sd->TickSpace - 1);
  378.  
  379.                         SetAPen(rp,pens[SHINEPEN]);
  380.                         Move(rp,x + 1,y);
  381.                         Draw(rp,x + 1,y + sd->TickSpace - 1);
  382.                     }
  383.                 }
  384.             }
  385.         }
  386.     }
  387. }
  388.  
  389. STATIC VOID
  390. EraseHose(struct RastPort *rp,LONG left,LONG top,LONG dimension,struct SliderClassData *sd)
  391. {
  392.     if(sd->IsVertical)
  393.     {
  394.         UWORD width        = (sd->ThumbWidth - 4) / 2;
  395.         UWORD height    = dimension;
  396.  
  397.         RectFill(rp,left,                         top,
  398.                     left + width - 1,             top + height - 1);
  399.  
  400.         RectFill(rp,left + sd->ThumbWidth - width,top,
  401.                     left + sd->ThumbWidth - 1,    top + height - 1);
  402.     }
  403.     else
  404.     {
  405.         UWORD width        = dimension;
  406.         UWORD height    = (sd->ThumbHeight - 4) / 2;
  407.  
  408.         RectFill(rp,left,top,left + width - 1,top + height - 1);
  409.         RectFill(rp,left,top + sd->ThumbHeight - height,left + width - 1,top + sd->ThumbHeight - 1);
  410.     }
  411. }
  412.  
  413. STATIC VOID
  414. DrawRailLeft(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
  415. {
  416.     if(sd->IsVertical)
  417.     {
  418.         if(sd->ThumbLeft > 0)
  419.         {
  420.             SetAPen(rp,pens[SHADOWPEN]);
  421.             Move(rp,left + sd->RailTop,top);
  422.             Draw(rp,left + sd->RailTop + 2,top);
  423.  
  424.             SetAPen(rp,pens[BACKGROUNDPEN]);
  425.             WritePixel(rp,left + sd->RailTop + 3,top);
  426.  
  427.             EraseHose(rp,left + sd->ThumbTop,top,1,sd);
  428.  
  429.             if(sd->ThumbLeft > 1)
  430.             {
  431.                 EraseHose(rp,left + sd->ThumbTop,top + 1,sd->ThumbLeft - 1,sd);
  432.                 RectFill(rp,left + sd->RailTop + 1,top + 1,left + sd->RailTop + 2,top + sd->ThumbLeft - 1);
  433.  
  434.                 SetAPen(rp,pens[SHADOWPEN]);
  435.                 Move(rp,left + sd->RailTop,top + 1);
  436.                 Draw(rp,left + sd->RailTop,top + sd->ThumbLeft - 1);
  437.  
  438.                 SetAPen(rp,pens[SHINEPEN]);
  439.                 Move(rp,left + sd->RailTop + 3,top + 1);
  440.                 Draw(rp,left + sd->RailTop + 3,top + sd->ThumbLeft - 1);
  441.             }
  442.         }
  443.     }
  444.     else
  445.     {
  446.         if(sd->ThumbLeft > 0)
  447.         {
  448.             SetAPen(rp,pens[SHADOWPEN]);
  449.             Move(rp,left,top + sd->RailTop);
  450.             Draw(rp,left,top + sd->RailTop + 2);
  451.  
  452.             SetAPen(rp,pens[BACKGROUNDPEN]);
  453.             WritePixel(rp,left,top + sd->RailTop + 3);
  454.  
  455.             EraseHose(rp,left,top + sd->ThumbTop,1,sd);
  456.  
  457.             if(sd->ThumbLeft > 1)
  458.             {
  459.                 EraseHose(rp,left + 1,top + sd->ThumbTop,sd->ThumbLeft - 1,sd);
  460.                 RectFill(rp,left + 1,top + sd->RailTop + 1,left + sd->ThumbLeft - 1,top + sd->RailTop + 2);
  461.  
  462.                 SetAPen(rp,pens[SHADOWPEN]);
  463.                 Move(rp,left + 1,top + sd->RailTop);
  464.                 Draw(rp,left + sd->ThumbLeft - 1,top + sd->RailTop);
  465.  
  466.                 SetAPen(rp,pens[SHINEPEN]);
  467.                 Move(rp,left + 1,top + sd->RailTop + 3);
  468.                 Draw(rp,left + sd->ThumbLeft - 1,top + sd->RailTop + 3);
  469.             }
  470.         }
  471.     }
  472. }
  473.  
  474. STATIC VOID
  475. DrawRailRight(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
  476. {
  477.     if(sd->IsVertical)
  478.     {
  479.         if(sd->ThumbLeft < sd->ThumbLast)
  480.         {
  481.             SetAPen(rp,pens[SHINEPEN]);
  482.             Move(rp,left + sd->RailTop + 1,top + sd->Height - 1);
  483.             Draw(rp,left + sd->RailTop + 3,top + sd->Height - 1);
  484.  
  485.             SetAPen(rp,pens[BACKGROUNDPEN]);
  486.             WritePixel(rp,left + sd->RailTop,top + sd->Height - 1);
  487.             EraseHose(rp,left + sd->ThumbTop,top + sd->Height - 1,1,sd);
  488.  
  489.             if(sd->ThumbLeft < sd->ThumbLast - 1)
  490.             {
  491.                 RectFill(rp,left + sd->RailTop + 1,top + sd->ThumbLeft + sd->ThumbHeight,left + sd->RailTop + 2,top + sd->Height - 2);
  492.                 EraseHose(rp,left + sd->ThumbTop,top + sd->ThumbLeft + sd->ThumbHeight,sd->ThumbLast - sd->ThumbLeft - 1,sd);
  493.  
  494.                 SetAPen(rp,pens[SHADOWPEN]);
  495.                 Move(rp,left + sd->RailTop,top + sd->ThumbLeft + sd->ThumbHeight);
  496.                 Draw(rp,left + sd->RailTop,top + sd->Height - 2);
  497.  
  498.                 SetAPen(rp,pens[SHINEPEN]);
  499.                 Move(rp,left + sd->RailTop + 3,top + sd->ThumbLeft + sd->ThumbHeight);
  500.                 Draw(rp,left + sd->RailTop + 3,top + sd->Height - 2);
  501.             }
  502.         }
  503.     }
  504.     else
  505.     {
  506.         if(sd->ThumbLeft < sd->ThumbLast)
  507.         {
  508.             SetAPen(rp,pens[SHINEPEN]);
  509.             Move(rp,left + sd->Width - 1,top + sd->RailTop + 1);
  510.             Draw(rp,left + sd->Width - 1,top + sd->RailTop + 3);
  511.  
  512.             SetAPen(rp,pens[BACKGROUNDPEN]);
  513.             WritePixel(rp,left + sd->Width - 1,top + sd->RailTop);
  514.             EraseHose(rp,left + sd->Width - 1,top + sd->ThumbTop,1,sd);
  515.  
  516.             if(sd->ThumbLeft < sd->ThumbLast - 1)
  517.             {
  518.                 RectFill(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->RailTop + 1,left + sd->Width - 2,top + sd->RailTop + 2);
  519.                 EraseHose(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->ThumbTop,sd->ThumbLast - sd->ThumbLeft - 1,sd);
  520.  
  521.                 SetAPen(rp,pens[SHADOWPEN]);
  522.                 Move(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->RailTop);
  523.                 Draw(rp,left + sd->Width - 2,top + sd->RailTop);
  524.  
  525.                 SetAPen(rp,pens[SHINEPEN]);
  526.                 Move(rp,left + sd->ThumbLeft + sd->ThumbWidth,top + sd->RailTop + 3);
  527.                 Draw(rp,left + sd->Width - 2,top + sd->RailTop + 3);
  528.             }
  529.         }
  530.     }
  531. }
  532.  
  533. STATIC VOID
  534. EraseSlider(struct RastPort *rp,LONG left,LONG top,UWORD *pens,struct SliderClassData *sd)
  535. {
  536.     EraseRect(rp,left,top,left + sd->Width - 1,top + sd->Height - 1);
  537. }
  538.  
  539. STATIC VOID
  540. DrawSlider(struct RastPort *rp,LONG left,LONG top,UWORD selected,struct SliderClassData *sd)
  541. {
  542.     LONG offset;
  543.  
  544.     if(selected)
  545.         offset = sd->ThumbWidth;
  546.     else
  547.         offset = 0;
  548.  
  549.     if(sd->IsVertical)
  550.         BltBitMapRastPort(&sd->ThumbBitMap,offset,0,rp,left + sd->ThumbTop,top + sd->ThumbLeft,sd->ThumbWidth,sd->ThumbHeight,0xC0);
  551.     else
  552.         BltBitMapRastPort(&sd->ThumbBitMap,offset,0,rp,left + sd->ThumbLeft,top + sd->ThumbTop,sd->ThumbWidth,sd->ThumbHeight,0xC0);
  553. }
  554.  
  555. /****************************************************************************/
  556.  
  557. #define G(o)    ((struct Gadget *)(o))
  558.  
  559. /****************************************************************************/
  560.  
  561. STATIC VOID
  562. DoSetMethod(Object *object,struct GadgetInfo *ginfo,...)
  563. {
  564.     va_list args;
  565.  
  566.     va_start(args,ginfo);
  567.     DoMethod(object,OM_SET,(struct TagItem *)args,ginfo);
  568.     va_end(args);
  569. }
  570.  
  571. STATIC VOID
  572. DoUpdateMethod(Object *object,struct GadgetInfo *ginfo,...)
  573. {
  574.     va_list args;
  575.  
  576.     va_start(args,ginfo);
  577.     DoMethod(object,OM_UPDATE,(struct TagItem *)args,ginfo,OPUF_INTERIM);
  578.     va_end(args);
  579. }
  580.  
  581. STATIC ULONG
  582. RenderMethod(
  583.     Class *                class,
  584.     Object *            object,
  585.     struct gpRender *    RenderInfo)
  586. {
  587.     struct SliderClassData *sd = INST_DATA(class,object);
  588.     struct RastPort *rp = RenderInfo->gpr_RPort;
  589.     LONG left = G(object)->LeftEdge,top = G(object)->TopEdge;
  590.     UWORD *pens = sd->DrawInfo->dri_Pens;
  591.  
  592.     SetDrMd(rp,JAM1);
  593.  
  594.     if(RenderInfo->gpr_Redraw != GREDRAW_UPDATE)
  595.     {
  596.         EraseSlider(rp,left,top,pens,sd);
  597.         DrawTicks(rp,left,top,pens,sd);
  598.     }
  599.  
  600.     DrawRailLeft(rp,left,top,pens,sd);
  601.     DrawRailRight(rp,left,top,pens,sd);
  602.     DrawSlider(rp,left,top,G(object)->Flags & GFLG_SELECTED,sd);
  603.  
  604.     if(G(object)->Flags & GFLG_DISABLED)
  605.     {
  606.         STATIC const UWORD Ghosting[2] = { 0x4444,0x1111 };
  607.  
  608.         SetAPen(rp,pens[SHADOWPEN]);
  609.         SetDrMd(rp,JAM1);
  610.  
  611.         SetAfPt(rp,(UWORD *)Ghosting,1);
  612.         RectFill(rp,left,top,left + G(object)->Width - 1,top + G(object)->Height - 1);
  613.         SetAfPt(rp,NULL,0);
  614.     }
  615.  
  616.     return(TRUE);
  617. }
  618.  
  619. STATIC VOID
  620. DisposeMethod(
  621.     Class *        class,
  622.     Object *    object)
  623. {
  624.     struct SliderClassData *sd = INST_DATA(class,object);
  625.  
  626.     SliderCleanup(sd);
  627. }
  628.  
  629. STATIC BOOL
  630. GetMethod(
  631.     Class *            class,
  632.     Object *        object,
  633.     struct opGet *    GetInfo)
  634. {
  635.     struct SliderClassData *sd = INST_DATA(class,object);
  636.     BOOL result;
  637.  
  638.     switch(GetInfo->opg_AttrID)
  639.     {
  640.         case SLA_Current:
  641.  
  642.             *GetInfo->opg_Storage = sd->ThumbPosition;
  643.             result = TRUE;
  644.             break;
  645.  
  646.         case SLA_Position:
  647.  
  648.             *GetInfo->opg_Storage = sd->ThumbLeft;
  649.             result = TRUE;
  650.             break;
  651.  
  652.         case SLA_Max:
  653.  
  654.             *GetInfo->opg_Storage = sd->ThumbMax;
  655.             result = TRUE;
  656.             break;
  657.  
  658.         case SLA_NumTicks:
  659.  
  660.             *GetInfo->opg_Storage = sd->NumTicks;
  661.             result = TRUE;
  662.             break;
  663.  
  664.         default:
  665.  
  666.             result = DoSuperMethodA(class,object,(Msg)GetInfo);
  667.             break;
  668.     }
  669.  
  670.     return(result);
  671. }
  672.  
  673. STATIC BOOL
  674. SetMethod(
  675.     Class *            class,
  676.     Object *        object,
  677.     struct opSet *    SetInfo)
  678. {
  679.     struct SliderClassData *sd = INST_DATA(class,object);
  680.     struct TagItem *tag,*list = SetInfo->ops_AttrList;
  681.     LONG redraw = GREDRAW_UPDATE;
  682.     BOOL rawPosition = FALSE;
  683.     BOOL updatePosition = FALSE;
  684.     BOOL result = FALSE;
  685.     BOOL refresh;
  686.     BOOL disabled;
  687.  
  688.     disabled = (BOOL)((G(object)->Flags & GFLG_DISABLED) != 0);
  689.  
  690.     refresh = DoSuperMethodA(class,object,(Msg)SetInfo);
  691.  
  692.     while((tag = NextTagItem(&list)) != NULL)
  693.     {
  694.         switch(tag->ti_Tag)
  695.         {
  696.             case GA_Disabled:
  697.  
  698.                 if(disabled != (BOOL)(tag->ti_Data != 0))
  699.                 {
  700.                     refresh = TRUE;
  701.                     redraw = GREDRAW_REDRAW;
  702.                 }
  703.  
  704.                 break;
  705.  
  706.             case SLA_Current:
  707.  
  708.                 result = TRUE;
  709.  
  710.                 if(sd->ThumbPosition != tag->ti_Data)
  711.                 {
  712.                     refresh = TRUE;
  713.  
  714.                     sd->ThumbPosition = tag->ti_Data;
  715.                     updatePosition = TRUE;
  716.                 }
  717.  
  718.                 break;
  719.  
  720.             case SLA_Max:
  721.  
  722.                 result = TRUE;
  723.  
  724.                 if(sd->ThumbMax != tag->ti_Data)
  725.                 {
  726.                     refresh = TRUE;
  727.                     redraw = GREDRAW_REDRAW;
  728.  
  729.                     sd->ThumbMax = tag->ti_Data;
  730.                     updatePosition = TRUE;
  731.                 }
  732.  
  733.                 break;
  734.  
  735.             case SLA_Position:
  736.  
  737.                 result = TRUE;
  738.  
  739.                 if(sd->ThumbLeft != tag->ti_Data)
  740.                 {
  741.                     refresh = TRUE;
  742.                     rawPosition = TRUE;
  743.  
  744.                     sd->ThumbLeft = tag->ti_Data;
  745.                     updatePosition = TRUE;
  746.                 }
  747.  
  748.                 break;
  749.  
  750.             case SLA_NumTicks:
  751.  
  752.                 result = TRUE;
  753.  
  754.                 if(sd->NumTicks != tag->ti_Data)
  755.                 {
  756.                     sd->NumTicks = tag->ti_Data;
  757.                     redraw = GREDRAW_REDRAW;
  758.                 }
  759.  
  760.                 break;
  761.         }
  762.     }
  763.  
  764.     if(refresh)
  765.     {
  766.         struct RastPort *rp;
  767.  
  768.         if(updatePosition)
  769.         {
  770.             if(rawPosition)
  771.             {
  772.                 if(sd->ThumbLeft > sd->ThumbLast)
  773.                     sd->ThumbLeft = sd->ThumbLast;
  774.  
  775.                 if(sd->ThumbLast == 0)
  776.                     sd->ThumbPosition = 0;
  777.                 else
  778.                     sd->ThumbPosition = (sd->ThumbLeft * sd->ThumbMax + (sd->ThumbLast / 2)) / sd->ThumbLast;
  779.             }
  780.             else
  781.             {
  782.                 if(sd->ThumbMax == 0)
  783.                     sd->ThumbLeft = 0;
  784.                 else
  785.                     sd->ThumbLeft = (sd->ThumbLast * sd->ThumbPosition) / sd->ThumbMax;
  786.  
  787.                 if(sd->ThumbLeft > sd->ThumbLast)
  788.                     sd->ThumbLeft = sd->ThumbLast;
  789.             }
  790.         }
  791.  
  792.         rp = ObtainGIRPort(SetInfo->ops_GInfo);
  793.         if(rp != NULL)
  794.         {
  795.             DoMethod(object,GM_RENDER,SetInfo->ops_GInfo,rp,redraw);
  796.  
  797.             ReleaseGIRPort(rp);
  798.         }
  799.     }
  800.  
  801.     return(result);
  802. }
  803.  
  804. STATIC Object *
  805. NewMethod(
  806.     Class *            class,
  807.     Object *        object,
  808.     struct opSet *    SetInfo)
  809. {
  810.     Object *result;
  811.  
  812.     result = (Object *)DoSuperMethodA(class,object,(Msg)SetInfo);
  813.     if(result != NULL)
  814.     {
  815.         struct SliderClassData *sd = INST_DATA(class,result);
  816.         BOOL failed = FALSE;
  817.         ULONG freedom = FREEHORIZ;
  818.         struct TagItem *tag,*list = SetInfo->ops_AttrList;
  819.         WORD reference = 0;
  820.  
  821.         sd->UseTicks = TICKS_None;
  822.  
  823.         while((tag = NextTagItem(&list)) != NULL)
  824.         {
  825.             switch(tag->ti_Tag)
  826.             {
  827.                 case PGA_Freedom:
  828.  
  829.                     freedom = tag->ti_Data;
  830.                     break;
  831.  
  832.                 case SLA_DrawInfo:
  833.  
  834.                     sd->DrawInfo = (struct DrawInfo *)tag->ti_Data;
  835.                     break;
  836.  
  837.                 case SLA_Current:
  838.  
  839.                     sd->ThumbPosition = tag->ti_Data;
  840.                     break;
  841.  
  842.                 case SLA_Max:
  843.  
  844.                     sd->ThumbMax = tag->ti_Data;
  845.                     break;
  846.  
  847.                 case SLA_UseTicks:
  848.  
  849.                     sd->UseTicks = tag->ti_Data;
  850.                     break;
  851.  
  852.                 case SLA_Reference:
  853.  
  854.                     reference = tag->ti_Data;
  855.                     break;
  856.             }
  857.         }
  858.  
  859.         switch(freedom)
  860.         {
  861.             case FREEVERT:
  862.  
  863.                 sd->IsVertical = TRUE;
  864.                 break;
  865.  
  866.             case FREEHORIZ:
  867.  
  868.                 sd->IsVertical = FALSE;
  869.                 break;
  870.  
  871.             default:
  872.  
  873.                 failed = TRUE;
  874.                 break;
  875.         }
  876.  
  877.         if(sd->DrawInfo == NULL)
  878.             failed = TRUE;
  879.  
  880.         if(NOT failed)
  881.         {
  882.             if(freedom == FREEVERT && G(result)->Height < 10)
  883.                 failed = TRUE;
  884.  
  885.             if(freedom == FREEHORIZ && G(result)->Width < 10)
  886.                 failed = TRUE;
  887.         }
  888.  
  889.         if(NOT failed)
  890.         {
  891.             LONG dimension,position;
  892.  
  893.             if(freedom == FREEVERT)
  894.                 dimension = G(result)->Height;
  895.             else
  896.                 dimension = G(result)->Width;
  897.  
  898.             if(SliderSetup(sd,reference,dimension) == FAILED)
  899.                 failed = TRUE;
  900.             else
  901.             {
  902.                 ULONG dimTag,posTag;
  903.  
  904.                 if(freedom == FREEVERT)
  905.                 {
  906.                     dimTag        = GA_Width;
  907.                     dimension    = sd->Width;
  908.  
  909.                     posTag        = GA_Left;
  910.                     position    = G(result)->LeftEdge + (G(result)->Width - sd->Width) / 2;
  911.                 }
  912.                 else
  913.                 {
  914.                     dimTag        = GA_Height;
  915.                     dimension    = sd->Height;
  916.  
  917.                     posTag        = GA_Top;
  918.                     position    = G(result)->TopEdge + (G(result)->Height - sd->Height) / 2;
  919.                 }
  920.  
  921.                 DoMethod(result,OM_SET,SetInfo->ops_AttrList,NULL);
  922.  
  923.                 DoSetMethod(result,NULL,
  924.                     dimTag,    dimension,
  925.                     posTag,    position,
  926.                 TAG_DONE);
  927.             }
  928.         }
  929.  
  930.         if(failed)
  931.         {
  932.             CoerceMethod(class,result,OM_DISPOSE);
  933.             result = NULL;
  934.         }
  935.     }
  936.  
  937.     return(result);
  938. }
  939.  
  940. STATIC VOID
  941. HandleSlide(
  942.     Object *            object,
  943.     struct SliderClassData *    sd,
  944.     struct gpInput *    InputInfo)
  945. {
  946.     LONG mousePosition;
  947.     BOOL isValid;
  948.  
  949.     if(sd->IsVertical)
  950.     {
  951.         mousePosition = InputInfo->gpi_Mouse.Y;
  952.  
  953.         isValid = (BOOL)(mousePosition >= 0 && mousePosition < G(object)->Height &&
  954.                          InputInfo->gpi_Mouse.X >= 0 && InputInfo->gpi_Mouse.X < G(object)->Width);
  955.     }
  956.     else
  957.     {
  958.         mousePosition = InputInfo->gpi_Mouse.X;
  959.  
  960.         isValid = (BOOL)(mousePosition >= 0 && mousePosition < G(object)->Width &&
  961.                          InputInfo->gpi_Mouse.Y >= 0 && InputInfo->gpi_Mouse.Y < G(object)->Height);
  962.     }
  963.  
  964.     if(isValid)
  965.     {
  966.         LONG direction = 0,size;
  967.  
  968.         if(sd->IsVertical)
  969.             size = sd->ThumbHeight;
  970.         else
  971.             size = sd->ThumbWidth;
  972.  
  973.         if(mousePosition < sd->ThumbLeft)
  974.         {
  975.             if(sd->ThumbPosition > 0)
  976.                 direction = -1;
  977.         }
  978.         else if (mousePosition >= sd->ThumbLeft + size)
  979.         {
  980.             if(sd->ThumbPosition + 1 <= sd->ThumbMax)
  981.                 direction = 1;
  982.         }
  983.  
  984.         if(direction != 0)
  985.         {
  986.             ULONG newThumbPosition = sd->ThumbPosition + direction;
  987.             LONG thumbLeft;
  988.  
  989.             if(sd->ThumbMax == 0)
  990.                 thumbLeft = 0;
  991.             else
  992.                 thumbLeft = (sd->ThumbLast * newThumbPosition) / sd->ThumbMax;
  993.  
  994.             if(thumbLeft > sd->ThumbLast)
  995.                 thumbLeft = sd->ThumbLast;
  996.  
  997.             if(direction < 0 && thumbLeft < mousePosition ||
  998.                direction > 0 && thumbLeft + size >= mousePosition)
  999.             {
  1000.                 if(direction > 0)
  1001.                     mousePosition -= size - 1;
  1002.  
  1003.                 DoUpdateMethod(object,InputInfo->gpi_GInfo,
  1004.                     SLA_Position,    mousePosition,
  1005.                 TAG_DONE);
  1006.             }
  1007.             else
  1008.             {
  1009.                 DoUpdateMethod(object,InputInfo->gpi_GInfo,
  1010.                     SLA_Current,    newThumbPosition,
  1011.                 TAG_DONE);
  1012.             }
  1013.         }
  1014.     }
  1015. }
  1016.  
  1017. STATIC ULONG
  1018. InputMethod(
  1019.     Class *                class,
  1020.     Object *            object,
  1021.     struct gpInput *    InputInfo)
  1022. {
  1023.     struct SliderClassData *sd = INST_DATA(class,object);
  1024.     ULONG result = GMR_MEACTIVE;
  1025.  
  1026.     if(InputInfo->gpi_IEvent->ie_Class == IECLASS_RAWMOUSE)
  1027.     {
  1028.         LONG position;
  1029.  
  1030.         switch(InputInfo->gpi_IEvent->ie_Code)
  1031.         {
  1032.             case SELECTUP:
  1033.  
  1034.                 result = GMR_REUSE | GMR_VERIFY;
  1035.                 break;
  1036.  
  1037.             case IECODE_NOBUTTON:
  1038.  
  1039.                 if(sd->DirectHit)
  1040.                 {
  1041.                     if(sd->IsVertical)
  1042.                         position = InputInfo->gpi_Mouse.Y + sd->ActiveOffset;
  1043.                     else
  1044.                         position = InputInfo->gpi_Mouse.X + sd->ActiveOffset;
  1045.  
  1046.                     if(position < 0)
  1047.                         position = 0;
  1048.                     else if (position > sd->ThumbLast)
  1049.                         position = sd->ThumbLast;
  1050.  
  1051.                     if(position != sd->ThumbLeft)
  1052.                     {
  1053.                         DoSetMethod(object,InputInfo->gpi_GInfo,
  1054.                             SLA_Position,    position,
  1055.                         TAG_DONE);
  1056.                     }
  1057.                 }
  1058.  
  1059.                 break;
  1060.         }
  1061.     }
  1062.  
  1063.     return(result);
  1064. }
  1065.  
  1066. STATIC ULONG
  1067. ActiveMethod(
  1068.     Class *                class,
  1069.     Object *            object,
  1070.     struct gpInput *    InputInfo)
  1071. {
  1072.     struct SliderClassData *sd = INST_DATA(class,object);
  1073.     ULONG result;
  1074.     struct RastPort *rp;
  1075.  
  1076.     rp = ObtainGIRPort(InputInfo->gpi_GInfo);
  1077.     if(rp != NULL)
  1078.     {
  1079.         if(sd->DirectHit)
  1080.         {
  1081.             G(object)->Flags |= GFLG_SELECTED;
  1082.             DoMethod(object,GM_RENDER,InputInfo->gpi_GInfo,rp,GREDRAW_UPDATE);
  1083.         }
  1084.  
  1085.         ReleaseGIRPort(rp);
  1086.  
  1087.         if(sd->IsVertical)
  1088.             sd->ActiveOffset = sd->ThumbLeft - InputInfo->gpi_Mouse.Y;
  1089.         else
  1090.             sd->ActiveOffset = sd->ThumbLeft - InputInfo->gpi_Mouse.X;
  1091.  
  1092.         if(NOT sd->DirectHit)
  1093.             HandleSlide(object,sd,InputInfo);
  1094.  
  1095.         result = GMR_MEACTIVE;
  1096.     }
  1097.     else
  1098.     {
  1099.         result = GMR_NOREUSE;
  1100.     }
  1101.  
  1102.     return(result);
  1103. }
  1104.  
  1105. STATIC ULONG
  1106. InactiveMethod(
  1107.     Class *                    class,
  1108.     Object *                object,
  1109.     struct gpGoInactive *    InactiveInfo)
  1110. {
  1111.     struct RastPort *rp;
  1112.  
  1113.     rp = ObtainGIRPort(InactiveInfo->gpgi_GInfo);
  1114.     if(rp != NULL)
  1115.     {
  1116.         struct SliderClassData *sd = INST_DATA(class,object);
  1117.  
  1118.         if(sd->DirectHit)
  1119.         {
  1120.             G(object)->Flags &= ~GFLG_SELECTED;
  1121.             DoMethod(object,GM_RENDER,InactiveInfo->gpgi_GInfo,rp,GREDRAW_UPDATE);
  1122.         }
  1123.  
  1124.         ReleaseGIRPort(rp);
  1125.     }
  1126.  
  1127.     return(0);
  1128. }
  1129.  
  1130. STATIC ULONG
  1131. HitTestMethod(
  1132.     Class *                class,
  1133.     Object *            object,
  1134.     struct gpHitTest *    HitInfo)
  1135. {
  1136.     struct SliderClassData *sd = INST_DATA(class,object);
  1137.     ULONG result;
  1138.  
  1139.     if(sd->IsVertical)
  1140.     {
  1141.         if(HitInfo->gpht_Mouse.Y >= sd->ThumbLeft &&
  1142.            HitInfo->gpht_Mouse.Y <  sd->ThumbLeft + sd->ThumbHeight &&
  1143.            HitInfo->gpht_Mouse.X >= sd->ThumbTop &&
  1144.            HitInfo->gpht_Mouse.X <  sd->ThumbTop + sd->ThumbWidth)
  1145.         {
  1146.             sd->DirectHit = TRUE;
  1147.         }
  1148.         else
  1149.         {
  1150.             sd->DirectHit = FALSE;
  1151.         }
  1152.  
  1153.         result = GMR_GADGETHIT;
  1154.     }
  1155.     else
  1156.     {
  1157.         if(HitInfo->gpht_Mouse.X >= sd->ThumbLeft &&
  1158.            HitInfo->gpht_Mouse.X <  sd->ThumbLeft + sd->ThumbWidth &&
  1159.            HitInfo->gpht_Mouse.Y >= sd->ThumbTop &&
  1160.            HitInfo->gpht_Mouse.Y <  sd->ThumbTop + sd->ThumbHeight)
  1161.         {
  1162.             sd->DirectHit = TRUE;
  1163.         }
  1164.         else
  1165.         {
  1166.             sd->DirectHit = FALSE;
  1167.         }
  1168.  
  1169.         result = GMR_GADGETHIT;
  1170.     }
  1171.  
  1172.     return(result);
  1173. }
  1174.  
  1175.  
  1176. /*****************************************************************************/
  1177.  
  1178. VOID
  1179. LTP_LevelGadgetDrawLabel(LayoutHandle *Handle,ObjectNode *Node,BOOL FullRefresh)
  1180. {
  1181.     if(Node->Label)
  1182.     {
  1183.         LevelExtra *Special = &Node->Special.Level;
  1184.         LONG Current = Node->Current;
  1185.  
  1186.         if(FullRefresh)
  1187.             LTP_DrawObjectLabel(Handle,Node);
  1188.  
  1189.         if(Special->LevelFormat)
  1190.         {
  1191.             UBYTE Buffer[256];
  1192.             struct RastPort *RPort;
  1193.             LONG LabelTop,LabelLeft;
  1194.             LONG LevelWidth,LevelLen;
  1195.  
  1196.             RPort = &Handle->RPort;
  1197.  
  1198.             switch(Special->LevelPlace)
  1199.             {
  1200.                 case PLACETEXT_LEFT:
  1201.  
  1202.                     LabelLeft    = Node->Left - INTERWIDTH;
  1203.                     LabelTop    = Node->Top + (Node->Height - Handle->GlyphHeight) / 2;
  1204.                     break;
  1205.  
  1206.                 case PLACETEXT_RIGHT:
  1207.  
  1208.                     LabelLeft    = Node->Left + Node->Width + INTERWIDTH + Special->MaxLevelWidth;
  1209.                     LabelTop    = Node->Top + (Node->Height - Handle->GlyphHeight) / 2;
  1210.                     break;
  1211.  
  1212.                 case PLACETEXT_ABOVE:
  1213.  
  1214.                     LabelLeft    = Node->Left + (Node->Width - Special->MaxLevelWidth) / 2 + Special->MaxLevelWidth;
  1215.                     LabelTop    = Node->Top - (Handle->GlyphHeight + INTERHEIGHT);
  1216.                     break;
  1217.  
  1218.                 case PLACETEXT_BELOW:
  1219.  
  1220.                     LabelLeft    = Node->Left + (Node->Width - Special->MaxLevelWidth) / 2 + Special->MaxLevelWidth;
  1221.                     LabelTop    = Node->Top + Node->Height + INTERHEIGHT;
  1222.                     break;
  1223.  
  1224.                 default:
  1225.  
  1226.                     return;    /* Note: only in case none of the alignment types matches; should never happen! */
  1227.             }
  1228.  
  1229.             LTP_SetPens(RPort,Handle->TextPen,Handle->BackgroundPen,JAM2);
  1230.  
  1231.             if(Special->DispFunc)
  1232.                 Current = (*Special->DispFunc)(Node->Host,Current);
  1233.  
  1234.             SPrintf(Buffer,Special->LevelFormat,Current);
  1235.  
  1236.             LevelLen = strlen(Buffer);
  1237.  
  1238.             LevelWidth = TextLength(RPort,Buffer,LevelLen);
  1239.  
  1240.             LTP_PrintText(RPort,Buffer,LevelLen,LabelLeft - LevelWidth,LabelTop);
  1241.  
  1242.             if(LevelWidth < Special->MaxLevelWidth)
  1243.                 LTP_EraseBox(RPort,LabelLeft - Special->MaxLevelWidth,LabelTop,Special->MaxLevelWidth - LevelWidth,Handle->GlyphHeight);
  1244.         }
  1245.     }
  1246. }
  1247.  
  1248. LONG
  1249. LTP_GetCurrentLevel(ObjectNode *Node)
  1250. {
  1251.     LONG Current,Max;
  1252.  
  1253.     GetAttr(SLA_Current,Node->Host,(ULONG *)&Current);
  1254.     GetAttr(SLA_Max,Node->Host,(ULONG *)&Max);
  1255.  
  1256.     if(Node->Special.Level.Freedom == FREEVERT)
  1257.         Current = Max - Current;
  1258.  
  1259.     return(Current + Node->Special.Level.Plus);
  1260. }
  1261.  
  1262. /*****************************************************************************/
  1263.  
  1264.  
  1265. ULONG SAVE_DS ASM
  1266. LTP_LevelClassDispatcher(REG(a0) Class *class,REG(a2) Object *object,REG(a1) Msg msg)
  1267. {
  1268.     ULONG result;
  1269.  
  1270.     switch(msg->MethodID)
  1271.     {
  1272.         case OM_NEW:
  1273.  
  1274.             result = (ULONG)NewMethod(class,object,(struct opSet *)msg);
  1275.             break;
  1276.  
  1277.         case OM_UPDATE:
  1278.         case OM_SET:
  1279.  
  1280.             result = SetMethod(class,object,(struct opSet *)msg);
  1281.             break;
  1282.  
  1283.         case OM_GET:
  1284.  
  1285.             result = GetMethod(class,object,(struct opGet *)msg);
  1286.             break;
  1287.  
  1288.         case GM_RENDER:
  1289.  
  1290.             result = RenderMethod(class,object,(struct gpRender *)msg);
  1291.             break;
  1292.  
  1293.         case GM_HITTEST:
  1294.  
  1295.             result = HitTestMethod(class,object,(struct gpHitTest *)msg);
  1296.             break;
  1297.  
  1298.         case GM_GOINACTIVE:
  1299.  
  1300.             result = InactiveMethod(class,object,(struct gpGoInactive *)msg);
  1301.             break;
  1302.  
  1303.         case GM_GOACTIVE:
  1304.  
  1305.             result = ActiveMethod(class,object,(struct gpInput *)msg);
  1306.             break;
  1307.  
  1308.         case GM_HANDLEINPUT:
  1309.  
  1310.             result = InputMethod(class,object,(struct gpInput *)msg);
  1311.             break;
  1312.  
  1313.         case OM_DISPOSE:
  1314.  
  1315.             DisposeMethod(class,object);
  1316.  
  1317.             /* Falls through to... */
  1318.  
  1319.         default:
  1320.  
  1321.             result = DoSuperMethodA(class,object,msg);
  1322.             break;
  1323.     }
  1324.  
  1325.     return(result);
  1326. }
  1327.  
  1328. #endif    /* DO_LEVEL_KIND */
  1329.